//TASK: Write a program that converts numbers to theirs text representation.
//Example:
//Input: 1123
//Output: one thousand one hundred twenty-three
//Test changes - xxxxxxxxxxxxxxxxxxxxx

//Written by HungNV - 28-08-2013
#include <iostream>
#include <string>
#include <conio.h>

using namespace std;

// Representation using Standard Dictionary Numbers - short scale: http://en.wikipedia.org/wiki/Names_of_large_numbers
//In English
const string MINUS = "Minus";   
const string Ones[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
const string Teens[] = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
const string Tens[] = { "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
const string hundred = "hundred";  
const string thousand = "thousand";  
const string scale[] = { "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion",
                         "nonillion", "decillion" , "undecillion", "duodecillion", "tredecillion", "quattuordecillion", "quindecillion",
                         "sexdecillion", "septendecillion", "octodecillion", "novemdecillion" };                         
//scale[] : from 10^6 to 10^66 - step = 3      
const char separate = '.'; //for float number - in English '.' ; in Russian (French, Vietnamese..) - ','
const string sep_spell = "point";

class Num2Text
{
      private:
              string str_num;     //input number
              bool   valid, minus;       //check for wrong/right input
              int    sep_pos;            //Possition of floating point, if exits
              string floating_part;      //String for floating part of number
              
      public:
             Num2Text()
             {
                       valid = false;       //init
                       minus = false;
                       sep_pos = -1;
             }
                       
             void input();         
             void representation();
             bool check_valid();
};
      
void Num2Text::input()
{
     cout << "Please enter a number = "; 
     cin >> str_num;
}

void Num2Text::representation()
{
     // Using Standard Dictionary Numbers - short scale: http://en.wikipedia.org/wiki/Names_of_large_numbers
     if (str_num == "0")
        cout<< Ones[0] <<" ";
     else
     {
        while( str_num.size()%3 != 0 )
            str_num = '0' + str_num; // insert '0' to number until size = 3k

        //Print sign of number
        if (minus) cout <<MINUS <<" ";

        for(int i = 0; i < str_num.size(); i += 3 ) // Processing with each 3 digits
        {
            // skip if all of 3 digits == '0'
            if((str_num[i] == '0') && (str_num[i+1] == '0') && (str_num[i+2] == '0') )
                continue;

            if( str_num[i + 0] > '0' )// print the hundreds of 3 digits
                cout << Ones[ str_num[i + 0] - '0'] << " " << hundred <<" ";

            if( str_num[i + 1] == '0' || str_num[i + 1] > '1' )// print tens and ones digits for non-teens case
            {
                if( str_num[i + 1] > '1' ) cout << Tens[ str_num[i + 1] - '0' - 2 ] << " ";
                if( str_num[i + 2] > '0' ) cout << Ones[ str_num[i + 2] - '0'] << " ";
            }
            else// inclusive teens case
                cout << Teens[ str_num[i + 2] - '0' ] << " ";

            // print scale of 10^3
            unsigned int j = ( str_num.size() - i )/3;
            if( j == 2 ) cout << thousand<<" ";
            else if( j > 2 )
            {
                cout <<scale[j-3] <<" ";
            }
        }     
      }   
      if (sep_pos !=-1)         //Represent floating part
           {
               cout <<sep_spell <<" ";
               for (int i  =0 ; i < floating_part.size() ; i ++)
                   cout << Ones[ floating_part[i] - '0'] << " ";
           }      
}

bool Num2Text::check_valid()
{
     int floating = 0;
        if (str_num[0] == '-')             //Check for sign of number
        {
           minus = true;  
           str_num.erase(0,1); 
        }  
        
        for(int i = 0; i < str_num.size(); i++)     
        {   
            if (str_num[i] == separate)    //Check for valid float number
               {
                           floating ++;
                           sep_pos = i;
               }
            else if( str_num[i] < '0' || str_num[i] > '9' )  //check if only digits
                return 0;
        }
        
        if (floating >1) //more than 1 char separate
           return 0;
        
        if (sep_pos != -1)   
        {
           floating_part = str_num.substr (sep_pos + 1, str_num.size() - sep_pos -1);// Copy floating part to new string
           str_num.erase(sep_pos, str_num.size() - sep_pos);           //delete floating part from num string number
        }
                
        if( str_num.size() > 66 )            // check for length of number. if longer than 66 then can't represent
            return 0;    
        
        return 1;
}

int main()
{
    Num2Text number;       // object number
    bool  checked = false;
    while (!checked)      //check for valid input number - do while input number is invalid
      {
             number.input();
             checked = number.check_valid();    
             if (!checked)            //input number is invalid
                cout<<"\nThe number is invalid or too long to represent.\n";       
       }
    number.representation(); //Representation
    getch();   
    return 0;    
}
    
